package config;

import annotations.MyBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * spring的配置类 相当于applicationContext.xml 用于替代xml配置
 * <p>
 * 1 @Configuration不可以是final类型；
 * 2 @Configuration不可以是匿名类；
 * 3 嵌套的configuration必须是静态类。
 * 1.必须以类的形式提供配置类, 允许通过生成的子类进行运行时增强(Cglib动态代理)。
 * 2.配置类必须是non-final的 编译报错
 * 3.配置类必须是non-local的（即不能在方法中声明）(non-local是不是翻译成非局部的比较好
 * 可以使用第4个约束的代码对 AppConfigAux 的访问级别修改成private试一试,会报错的, 这一步的测试体现该类不能是private级别。
 * 不能在方法中声明 表示的是不能是局部内部类)
 * 4.必须将任何嵌套配置类声明为static。（不声明也可以正常使用？声明为静态是为了隔离-静态类行为上和顶层的类相似，不能访问外部类的成员，只能访问静态成员）
 * 5.@Bean方法可能不会反过来创建进一步的配置类（任何此类实例都将被视为常规bean，其配置注释仍未被检测到）。
 *
 * @author 黑马程序员 *
 * @Company http://www.itheima.com
 */
@Configuration
public class SpringConfiguration {

    @Resource
    private DataSource dataSource;
    /**
     * 增加数据源对象
     * autowireCandidate: 用于指定是否支持自动按类型注入到其他bean中。
     * 只影响@Autowired注解的使用。不影响 @Resource注解注入。默认值为true，
     * 意为允许使用自动按类型注入。
     */
    @Bean(value = "dataSource", autowireCandidate = false)
    public DataSource createDataSource(){
        return new DriverManagerDataSource();
    }

//    @Bean(value = "jdbcTemplate")
//    public JdbcTemplate createJdbcTemplate(DataSource dataSource){
//        return new JdbcTemplate(dataSource);
//    }

    /**
     * 作用：它写在方法上，表示把当前方法的返回值存入spring的ioc容器。
     * 同时还可以出现在注解上，作为元注解来使用。 属性：name:用于指定存入spring容器中bean的标识。支持指定多个标识。当不指定该属性时，默认值是当前 方法的名称。
     * value:此属性是在4.3.3版本之后加入的。它和name属性的作用是一样的。
     * autowireCandidate: 用于指定是否支持自动按类型注入到其他bean中。
     * 只影响@Autowired注解的使用。不影响 @Resource注解注入。默认值为true，意为允许使用自动按类型注入。
     * initMethod: 用于指定初始化方法。
     * destroyMethod: 用于指定销毁方法。
     * 使用场景： 通常情况下，在基于注解的配置中，我们用于把一个类存入spring的ioc容器中，
     * 首先考虑的是使用 @Component以及他的衍生注解。但是如果遇到要存入容器的Bean对象不是我们写的类，
     * 此时无法在类上添加 @Component注解，这时就需要此注解了。
     * 示例：例如，在我们配置JdbcTemplate使用Spring内置数据源DriverManagerDataSource时，
     * 数据源类 是spring-jdbc这个jar包中类，此时我们无法编辑，
     * 在上面加注解，此时就可以使用@Bean注解配置。
     * @return
     */
//    @Bean(value = "jdbcTemplate")
//    public JdbcTemplate createJdbcTemplate(){
//        return new JdbcTemplate(dataSource);
//    }

    @MyBean(value = "jdbcTemplate")
    public JdbcTemplate createJdbcTemplate(){
        return new JdbcTemplate(dataSource);
    }

}
